package com.open4cn.simulator.device;

import com.open4cn.simulator.core.device.DefaultDeviceStatusRepository;
import com.open4cn.simulator.core.device.DeviceStatus;
import com.open4cn.simulator.core.device.DeviceStatusDO;
import com.open4cn.simulator.core.device.IDeviceStatusChanger;
import com.open4cn.simulator.core.device.IDeviceStatusHandlerFactory;
import com.open4cn.simulator.core.device.IDeviceStatusRecover;
import com.open4cn.simulator.core.device.IDeviceStatusRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.concurrent.ConcurrentHashMap;

/**
 * @author yinxiaopeng
 * @version 1.0.0
 * @company 致景科技
 * @department 飞梭BU/研发
 * @description
 * @Email yinxiaopeng@zj.tech
 * @date 2022-05-15 01:31
 */
public class DeviceStatusManager {
    private static Logger logger = LoggerFactory.getLogger(DeviceStatusManager.class);

    // k= 设备唯一标识
    private ConcurrentHashMap<String, DeviceStatus> deviceStatusContainer = new ConcurrentHashMap<>();

    private IDeviceStatusRepository repository = new DefaultDeviceStatusRepository();


    /**
     * 获取指定设备的状态
     *
     * @param deviceId
     * @return
     */
    public DeviceStatus get(String deviceId) {
        if (null != deviceId && deviceId.length() != 0) {
            return deviceStatusContainer.get(deviceId);
        }
        return null;
    }

    /**
     * 存储
     *
     * @param deviceId
     * @param deviceStatus
     */
    public void put(String deviceId, DeviceStatus deviceStatus) {
        deviceStatusContainer.put(deviceId, deviceStatus);
    }


    /**
     * 将设备状态持久化
     *
     * @param deviceId
     * @return
     */
    public boolean persistence(String deviceId) {
        return persistence(deviceId, getRepository());
    }


    /**
     * 使用指定的存储器持久化设备状态
     *
     * @param deviceId
     * @param repository
     * @return
     */
    public boolean persistence(String deviceId, IDeviceStatusRepository repository) {
        if (null != repository && exists(deviceId)) {
            logger.info("触发{}设备状态持久化", deviceId);
            DeviceStatus deviceStatus = get(deviceId);
            return repository.save(new DeviceStatusDO(deviceStatus));
        }
        return true;
    }


    /**
     * 加载设备状态
     *
     * @param deviceId
     * @return
     */
    public DeviceStatus load(String deviceId) {
        return load(deviceId, getRepository());
    }


    /**
     * 加载设备状态
     *
     * @param deviceId
     * @param repository
     * @return
     */
    public DeviceStatus load(String deviceId, IDeviceStatusRepository repository) {
        DeviceStatus deviceStatus = null;
        if (null != repository) {
            DeviceStatusDO deviceStatusDO = repository.get(deviceId);
            if (null != deviceStatusDO) {
                logger.info("触发{}设备状态加载", deviceId);
                IDeviceStatusHandlerFactory statusHandlerFactory = DeviceStatusHandlerRoute.route(deviceStatusDO.getBrand(), deviceStatusDO.getModel());
                IDeviceStatusRecover recover = statusHandlerFactory.getRecover();
                deviceStatus = recover.recover(deviceStatusDO);
            }
        }
        return deviceStatus;
    }


    /**
     * 移除
     *
     * @param deviceId
     * @return
     */
    public boolean remove(String deviceId) {
        if (exists(deviceId)) {
            logger.info("移除{}设备状态", deviceId);
            deviceStatusContainer.remove(deviceId);
        }
        return true;
    }


    /**
     * 更改设备状态
     *
     * @param deviceId
     * @param key
     * @param value
     */
    public void changeStatus(String deviceId, String key, Object value) {
        if (null == key || null == value) {
            return;
        }
        if (exists(deviceId)) {
            logger.info("触发{}设备状态{}修改", deviceId, key);
            DeviceStatus deviceStatus = get(deviceId);
            IDeviceStatusHandlerFactory statusHandlerFactory = DeviceStatusHandlerRoute.route(deviceStatus.getBrand(), deviceStatus.getModel());
            IDeviceStatusChanger changer = statusHandlerFactory.getChanger();
            changer.change(deviceStatus, key, value);
        }
    }

    /**
     * 是否存在
     *
     * @param deviceId
     * @return
     */
    public boolean exists(String deviceId) {
        return null != get(deviceId);
    }

    public void setRepository(IDeviceStatusRepository repository) {
        this.repository = repository;
    }

    public IDeviceStatusRepository getRepository() {
        return repository;
    }

    /**
     * --------------------------------------------
     **/

    private DeviceStatusManager() {
    }

    private static class HolderClass {
        private static final DeviceStatusManager instance = new DeviceStatusManager();
    }

    public static DeviceStatusManager getInstance() {
        return DeviceStatusManager.HolderClass.instance;
    }
}
